/*
Sample program for use with IBM WebSphere Message Broker
(c) Copyright International Business Machines Corporation 2009, 2010
Licensed Materials - Property of IBM
*/

package com.ibm.mqsi.tcpip;

import java.util.List;

import com.ibm.broker.javacompute.MbJavaComputeNode;
import com.ibm.broker.plugin.*;

public class TCPIPAsync_UpdateLocalEnv extends MbJavaComputeNode {

        @SuppressWarnings("unchecked") //we acknowledge we have a raw list
	public void evaluate(MbMessageAssembly inAssembly) throws MbException {
		// Define the output terminal to be used.
		MbOutputTerminal out = getOutputTerminal("out");

		// Get the input message 
		MbMessage inMessage = inAssembly.getMessage();

		// Get the input LocalEnvironment 
		MbMessage inLocalEnv = inAssembly.getLocalEnvironment();
		
		/*
		 * Note - We have not created an "Out" message assembly, message or local environment.
		 * As this is essentially a routing function, and we are not altering the message body,
		 * there is no need to operate on a new copy of the message body. 
		 * There would be a performance overhead in doing so.
		 * 
		 * We are modifying the local environment, but are able to modify the input local environment directly.
		 * Again, this avoids the performance overhead of creating a copy.
		 * One potential consequence of modifying the input local environment directly is in error situations.
		 * If the message flow rolls back to before this code is called, the modifications we have made to the 
		 * input local environment will remain. This would be avoided had we created a separate output local environment.		
		*/

		try {		
			// Use an XPath query to find any <Hostname> elements with the specified path in the XML message body, if present.
			// This returns a list of any <Hostname> elements found.
			List<MbElement> hostnameElements = (List<MbElement>) inMessage.evaluateXPath("/SaleEnvelope/Header/Hostname"); 

			// Check to see if any <Hostname> elements were found in the input message with the specified path.
			if (!hostnameElements.isEmpty()) {
				// At least one <Hostname> element was found. We assume that a corresponding <Port> element is also present.
				// Therefore the hostname and port specified in the properties of the TCPClientOutput node later
				// in the flow will be overridden by these values, using the LocalEnvironment.
				
				// Define variables to be used for storing the hostname and port.
				String hostname="";
				String port_string="";
				int port=0;

				// Get the first element in the list (Note there is only one expected in the input message anyway).
				MbElement hostnameElement = (MbElement) hostnameElements.get(0); 

				// Get the hostname to be used for the TCPIPClientOutput node later in the flow.
				hostname = (String) hostnameElement.getValue().toString();

				// Get the port to be used for the TCPIPClientOutput node later in the flow by navigating to the
				// 'Port' element from the 'Hostname' element. It is expected to be the next sibling in the message tree.
				port_string = (String) hostnameElement.getNextSibling().getValue().toString();
				port = Integer.parseInt(port_string);

				// Update the LocalEnvironment with the hostname to be used for TCPIPClientOutput node later in the flow.
				// '?' is used to select an element, or create and select it if it doesn't exist.
				MbXPath localEnv = new MbXPath("?Destination/?TCPIP/?Output/?Hostname[set-value('" + hostname + "')]");

				// We need to call evaluateXPath on the root element of the LocalEnvironment message tree to update it
				inLocalEnv.getRootElement().evaluateXPath(localEnv);

				// Update the LocalEnvironment with the port to be used for TCPIPClientOutput node later in the flow.
				// '?' is used to select an element, or create and select it if it doesn't exist.
				localEnv = new MbXPath("?Destination/?TCPIP/?Output/?Port[set-value(" + port + ")]");

				// We need to call evaluateXPath on the root element of the LocalEnvironment message tree to update it
				inLocalEnv.getRootElement().evaluateXPath(localEnv);
				
			}

			// If there were no <Hostname> elements found above then the hostname and port specified in the properties of the
			// TCPClientOutput node later in the flow will be used as normal.

			// Propagate the message to the output terminal.
			out.propagate(inAssembly);
		
		} finally {
			
		}
	}
}
